﻿using System;
using System.Configuration;
using System.Diagnostics;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using xxpl1.Cache;
using xxpl1.GAE;
using xxpl1.Log;
using xxpl1.Utils;

namespace ProxyUI
{
    internal class NbApplicationContext : ApplicationContext
    {
        public NbApplicationContext(Form mainForm)
            : base(mainForm)
        {

        }
        protected override void OnMainFormClosed(object sender, System.EventArgs e)
        {
            if (Settings.Instance.EnableCache)
                DiskCacheFactory.GetDiskCache().Dispose();

            base.OnMainFormClosed(sender, e);
        }
    }
    internal static class Program
    {
        private static readonly Regex regex = new Regex("CN=[^\\.]+\\.google\\.com", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        /// <summary>
        ///   The main entry point for the application.
        /// </summary>
        //[STAThread]
        private static void Main()
        {
            ServicePointManager.MaxServicePointIdleTime = int.Parse(ConfigurationManager.AppSettings["IdleTime"]) * 1000;
            ServicePointManager.ServerCertificateValidationCallback += TrustAll;

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["Chrome"]))
            {
                RunChrome();
            }
            else
                RunDefault();
        }

        private static void RunChrome()
        {
            Process chromeProcess = Process.Start(ConfigurationManager.AppSettings["Chrome"]);
            if (chromeProcess != null)
            {
                Task.Factory.StartNew(DnsHelper.TestAccessbility);

                xxpl1.Proxy.HttpListener listener = new xxpl1.Proxy.HttpListener(Settings.Instance.Port);

                listener.Start();

                chromeProcess.WaitForExit();
            }
        }

        private static void RunDefault()
        {
            LogManager.SetLogger(new FormAppender());

            ApplicationContext context = new NbApplicationContext(new MainForm());

            Application.Run(context);
        }

        private static bool TrustAll(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
        {
            if (sslpolicyerrors == SslPolicyErrors.None)
                return true;
            if (sslpolicyerrors == SslPolicyErrors.RemoteCertificateNameMismatch)
            {
                return regex.IsMatch(certificate.Subject);
            }

            LogManager.GetLogger("Cert").DebugFormat("Cert rejected.{0},{1}", certificate.Subject, certificate.Issuer);
            return false;
        }
    }
}